package org.timeticker.impl;

import org.timeticker.ObjectList;
import org.timeticker.ObjectListListener;

import java.util.ArrayList;
import java.util.List;

/**
 * Abstract object list with ArrayList as underlaying implementation
 *
 * @author Ivan Latysh
 * @version 0.1
 * @since 10-Aug-2007 : 6:40:54 PM
 */
public abstract class AbstractObjectList<T> implements ObjectList<T>{

  /** Objects list */
  protected final List<T> objects = new ArrayList<T>();
  /** Listeners array */
  protected final List<ObjectListListener> listeners = new ArrayList<ObjectListListener>();
  
  /** MOdified flag */
  protected boolean modified;

  /** {@inheritDoc} */
  public void addListener(ObjectListListener l) {
    listeners.add(l);
  }

  /** {@inheritDoc} */
  public void removeListener(ObjectListListener l) {
    listeners.remove(l);
  }

  /** {@inheritDoc} */
  public List<T> getObjects() {
    return objects;
  }

  /** {@inheritDoc} */
  public void setObjects(List<T> objects) {
    // clear current objects
    objects.clear();
    // add given objects
    this.objects.addAll(objects);
    // fire list changed event
    fireListChanged();
  }

  /** {@inheritDoc} */
  public boolean isModified() {
    return modified;
  }

  /** {@inheritDoc} */
  public void setModified(boolean modified) {
    this.modified = modified;
  }

  /** {@inheritDoc} */
  public int size() {
    return objects.size();
  }

  /** {@inheritDoc} */
  public boolean add(T object) {
    boolean added = objects.add(object);
    if (added) fireObjectAdded(0, object);
    return added;
  }

  /** {@inheritDoc} */
  public boolean set(int index, T object) {
    objects.set(index, object);
    fireObjectChanged(0, object);
    return true;
  }

  /** {@inheritDoc} */
  public boolean remove(T object) {
    boolean removed = objects.remove(object);
    if (removed) fireObjectRemoved(0, object);
    return removed;
  }

  /** {@inheritDoc} */
  public int indexOf(T object) {
    return objects.indexOf(object);
  }

  /** {@inheritDoc} */
  public T get(int index) {
    return objects.get(index);
  }

  /** {@inheritDoc} */
  public boolean contains(T object) {
    return objects.contains(object);
  }

  /**
   * Fire object added event
   *
   * @param index object index
   * @param object object that has been added
   */
  protected void fireObjectAdded(int index, T object){
    modified = true;
    for(ObjectListListener l : listeners) l.objectAdded(this, index, object);
  }

  /**
   * Fire object removed event
   *
   * @param index object index
   * @param object object
   */
  protected void fireObjectRemoved(int index, T object){
    modified = true;
    for(ObjectListListener l : listeners) l.objectRemoved(this, index, object);
  }

  /**
   * Fire object changed event
   *
   * @param index object index
   * @param object object
   */
  protected void fireObjectChanged(int index, T object){
    modified = true;
    for(ObjectListListener l : listeners) l.objectChanged(this, index, object);
  }

  /**
   * Fire list changed
   */
  protected void fireListChanged(){
    modified = true;
    for(ObjectListListener l : listeners) l.listChanged(this);
  }

}
